<template>
  <div class="h-100 link-topo">
    <div id="linkTopo" style="height: 100%" />
    <!-- 点击光缆事件弹窗 -->
    <div v-if="showProp" class="func-btns" :style="clickPosition">
      <div class="relative">
        <!-- 实际显示 -->
        <div slot="reference" class="flex justify-between align-center text-holder channel-item no-wrap">
          <span class="flex-1">
            {{ $utils.handleServiceI18n(activeChannel.startPort.bizName) }}
          </span>
          <span v-if="activeChannel.fiber">
            {{ activeChannel.fiber.fiberName }}
          </span>
          <span class="flex-1">
            {{ $utils.handleServiceI18n(activeChannel.endPort.bizName) }}
          </span>
        </div>
        <el-select
          :value="activeChannel.channelId"
          style="width: 300px"
          @change="activeChannelChange"
        >
          <el-option
            v-for="channel in activeChannelList"
            :key="channel.channelId"
            :value="channel.channelId"
            label=" "
          >
            <div class="flex justify-between align-center channel-item">
              <span class="flex-1" :title="$utils.handleServiceI18n(channel.startPort.bizName)">
                {{ $utils.handleServiceI18n(channel.startPort.bizName) }}
              </span>
              <span v-if="channel.fiber" :title="channel.fiber.fiberName">
                {{ channel.fiber.fiberName }}
              </span>
              <span
                class="flex-1 text-right"
                :title="$utils.handleServiceI18n(channel.endPort.bizName)"
              >
                {{ $utils.handleServiceI18n(channel.endPort.bizName) }}
              </span>
            </div>
          </el-option>
        </el-select>
      </div>
      <div class="flex justify-between mt-5">
        <el-button @click="showProp = false">{{ $t('CANCEL') }}</el-button>
        <el-button type="primary" @click="changeChannel">{{ $t('CONFIRM') }}</el-button>
      </div>
    </div>
    <!-- 点击新增的网段弹窗 -->
    <div v-if="showNewProp" class="func-btns" :style="clickPosition">
      <div class="flex font-small">
        <div class="mr-5">
          {{ activeChannel.startNode.nodeName }}
          <el-select :value="activeChannel.startPortId" @change="aPortChange">
            <el-option
              v-for="port in aPortList"
              :key="port.portId"
              :value="port.portId"
              :label="port.bizName"
            />
          </el-select>
        </div>
        <div>
          {{ activeChannel.endNode.nodeName }}
          <el-select :value="activeChannel.endPortId" @change="zPortChange">
            <el-option
              v-for="port in zPortList"
              :key="port.portId"
              :value="port.portId"
              :label="port.bizName"
            />
          </el-select>
        </div>
      </div>
      <div class="flex justify-between mt-5">
        <el-button @click="showNewProp = false">{{ $t('CANCEL') }}</el-button>
        <el-button type="primary" @click="changeChannel">{{ $t('CONFIRM') }}</el-button>
      </div>
    </div>
  </div>
</template>
<script>
  import { mapGetters } from 'vuex'
  import { Graph, Shape } from '@antv/x6'
  import cableFiberApi from '@/api/oen/CableFiberApi'
  import segmentChannelApi from '@/api/oen/SegmentChannelApi'
  import nodeApi from '@/api/oen/NodeApi'
  import getThemeColor from '@/utils/themesColor'
  import { deepClone } from '@/utils/common'

  export default {
    props: {
      routeList: {
        type: Array,
        default: () => {}
      },
      leftData: {
        type: Object,
        default: () => {}
      },
      migrateRoute: {
        type: Object,
        default: () => {}
      }
    },
    data() {
      return {
        showProp: false,
        clickPosition: {
          left: 0,
          top: 0
        },
        mainChannel: [],
        mockJson: '',
        topoData: [],
        mapData: {},
        graph: null,
        allNodeList: [],
        allEdgeList: [],
        channelCount: 1,
        ChannelData: {},
        cableData: {},
        nodePortData: {},
        mainRouteReady: false,
        migrateRouteReady: false,
        imgData: {
          AFS: require('@/assets/img/gis/afs.png'),
          ODF: require('@/assets/img/gis/odf.png'),
          TRANSPORT: require('@/assets/img/gis/transport.png'),
          LIGHT_SPLIT: require('@/assets/img/gis/light_split.png'),
          CLUSTER: require('@/assets/img/gis/cluster.png')
        },
        colorData: {
          // 多主题颜色获取
          normal: getThemeColor('topoColor') || '#A2B1C3',
          damage: getThemeColor('topoDamage') || 'red',
          highLight: getThemeColor('topoHighLight') || '#E69318',
          alwaysHighLight: getThemeColor('alwaysHighLight') || '#12f10f',
          fontColor: getThemeColor('topoColor') || '#333'
        },
        activeData: [],
        removeData: [],
        activeChannelList: [],
        activeChannel: {},
        activeEdge: null,
        showNewProp: false,
        aPortList: [],
        zPortList: [],
        initTopo: '',
        topoPortData: {},
        shownEdgeLabel: []
      }
    },
    computed: {
      ...mapGetters(['baseRegionList'])
    },
    mounted() {
      this.channelCount = this.leftData.mainData.length
      this.createMap()
      this.formateMainData()
      this.formateMigrateRoute()
      this.getAllPort()
      // console.log('this.allNodeList', this.allNodeList)
      // console.log('this.allEdgeList', this.allEdgeList)
    },
    methods: {
      fromateAllNode() {
        this.allNodeList = this.allNodeList.map(i => {
          const items = []
          if (i.lineType === 'migrate' && i.portList.length === this.channelCount) {
            const newPort = []
            // console.log('allNodeList', i)
            i.portList.forEach(j => {
              const newItem = this.nodePortData[i.nodeId]
                ? this.nodePortData[i.nodeId].find(z => z.portId === j.connPortId)
                : {}
              j.connPortData = newItem
              newPort.push({
                nodeId: i.nodeId,
                portId: j.connPortId,
                connPortData: j,
                ...newItem,
                x: j.x === 60 ? 0 : 60,
                y: j.y
              })
            })
            i.portList = [...i.portList, ...newPort]
          }
          const insideEdge = []
          i.portList.forEach((j, jIndex) => {
            // console.log('portData', j)
            if (i.portList.some(z => z.portId === j.connPortId)) {
              const edgeItem = {
                startNode: i,
                endNode: i,
                startNodeId: i.nodeId,
                endNodeId: i.nodeId,
                startPortId: j.portId,
                startPort: j,
                endPort: j.connPortData,
                endPortId: j.connPortId,
                id: j.portId + '_' + j.connPortId,
                label: '',
                lineType: i.lineType,
                from: j.portId,
                fromCell: i.nodeId,
                toCell: i.nodeId,
                to: j.connPortId
              }
              if (!insideEdge.some(z => z.from === j.connPortId && z.to === j.portId)) {
                insideEdge.push(edgeItem)
              }
            }
            j.stationId = i.stationId
            items.push({
              id: j.portId,
              group: j.x === 0 ? 'in' : 'out',
              label: {
                position: { args: { x: j.x === 0 ? -3 : 3, y: -5 }}
              },
              data: j,
              attrs: {
                text: {
                  text:
                    this.$utils.handleServiceI18n(j.bizName) || this.getPortName(j.nodeId, j.portId)
                }
              },
              args: {
                x: j.x,
                y: j.y
              }
            })
            this.topoPortData[j.portId] = j
          })
          this.allEdgeList = [...this.allEdgeList, ...insideEdge]
          const nodeItem = {
            ...i,
            items: items
          }
          return nodeItem
        })
        this.renderMap()
      },
      getPortName(nodeId, portId) {
        const portData = this.nodePortData[nodeId]
          ? this.nodePortData[nodeId].find(z => z.portId === portId)
          : null
        // console.log('portData', portData)
        return portData ? this.$utils.handleServiceI18n(portData.bizName) : ''
      },
      // 获取所有设备的端口列表
      getAllPort() {
        if (!this.mainRouteReady || !this.migrateRouteReady) return
        // console.log('this.allNodeList', this.allNodeList)
        const nodeIds = []
        const deviceIds = []
        const nodeStation = {}
        this.allNodeList.forEach(i => {
          nodeStation[i.nodeId] = i.stationId
          if (i.nodeType === 'AOCC' || i.nodeType === 'CLUSTER') {
            deviceIds.push(i.nodeId)
          } else {
            nodeIds.push(i.nodeId)
          }
        })
        nodeApi.portInfo({
          nodeIds: nodeIds,
          deviceIds: deviceIds
        }).then(res => {
          Object.keys(res).forEach(i => {
            res[i].forEach(j => {
              j.stationId = nodeStation[i]
              j.portName = this.$utils.handleServiceI18n(j.portName)
              j.bizName = this.$utils.handleServiceI18n(j.bizName)
            })
          })
          this.nodePortData = res
          this.fromateAllNode()
        })
      },
      // 渲染布局
      renderMap() {
        const stationList = []
        this.allNodeList.forEach(i => {
          const existStation = stationList.find(j => j.regionId === i.stationId)
          if (existStation) {
            existStation.nodeList.push(i)
          } else {
            const stationData = this.baseRegionList.find(j => j.regionId === i.stationId)
            i.stationData = stationData
            const item = {
              ...stationData,
              nodeList: [i]
            }
            stationList.push(item)
          }
        })
        let mainStationX = 50
        let migrateStationX = 50
        stationList.forEach((i, index) => {
          const mainNodes = i.nodeList.filter(j => j.lineType === 'main')
          const migrateNodes = i.nodeList.filter(j => j.lineType === 'migrate')
          mainNodes.forEach((j, jIndex) => {
            j.x = mainStationX + 50 + 150 * jIndex
            j.y = 100
          })
          const maxLength = Math.max(mainNodes.length, migrateNodes.length)
          i.width = (maxLength - 1) * 150 + 160
          i.height = mainNodes.length === 0 || migrateNodes.length === 0 ? 150 : 280
          if (mainNodes.length === 0) {
            i.x = migrateStationX
            i.y = 480
            migrateStationX = migrateStationX + migrateNodes.length * 150 + 50
          } else {
            i.x = mainStationX
            i.y = 50
            mainStationX = mainStationX + maxLength * 150 + 150
          }
          migrateNodes.forEach((j, jIndex) => {
            j.x = i.x + 50 + 150 * jIndex
            j.y = i.y + (mainNodes.length === 0 ? 40 : 180)
          })
          i.nodeList = [...mainNodes, ...migrateNodes]
          const parent = this.graph.addNode(this.createStation(i))
          i.nodeList.forEach(j => {
            const child = this.graph.addNode(this.createNode(j))
            parent.addChild(child)
          })
        })
        // console.log('stationList', stationList)
        this.allEdgeList.forEach(i => {
          this.graph.addEdge(this.createEdge(i))
        })
        this.initTopo = this.getMapData()
        const that = this
        this.graph.on('edge:removed', evt => {
          that.removeEdge(evt)
        })
        this.graph.on('edge:added', evt => {
          that.addEdge(evt)
        })
      },
      // 整合目标链路
      formateMigrateRoute() {
        console.log('this.migrateRoute', this.migrateRoute)
        const segmentList = this.migrateRoute.segmentList
        segmentChannelApi
          .getBySegmentIdList({ ids: segmentList.map(i => i.segmentId).join() })
          .then(res => {
            segmentList.forEach(j => {
              if (
                j.startNodeId !== res[j.segmentId][0].startNodeId &&
                j.endNodeId !== res[j.segmentId][0].endNodeId
              ) {
                res[j.segmentId] = res[j.segmentId].map(i => {
                  const item = {
                    startNodeId: i.endNodeId,
                    startPortId: i.endPortId,
                    startPortCategory: i.endPortCategory,
                    startNode: i.endNode,
                    startPort: i.endPort,
                    endNodeId: i.startNodeId,
                    endPortId: i.startPortId,
                    endPortCategory: i.startPortCategory,
                    endPort: i.startPort,
                    endNode: i.startNode
                  }
                  return { ...i, ...item }
                })
              }
            })
            Object.keys(res).forEach(i => {
              res[i] = res[i].filter(
                j => j.status !== 'MAIN' && !this.mainChannel.some(z => z.channelId === j.channelId)
              )
            })
            this.ChannelData = res
            // console.log('this.ChannelData', res)
            segmentList.forEach((i, index) => {
              const segItem = res[i.segmentId][0] || i
              this.addNode(segItem, index, true, 1)
              this.formateEdge({ ...segItem, cableName: i.cable.cableName }, true)
              if (this.channelCount === 2) {
                const segItem2 = res[i.segmentId][1] || i
                this.addNode(segItem2, index, true, 2)
                this.formateEdge({ ...segItem2, cableName: i.cable.cableName }, true)
              }
            })
            this.migrateRouteReady = true
            this.getAllPort()
          })
      },
      // 整合主链路
      formateMainData() {
        console.log('this.leftData', this.leftData)
        const mainData = this.leftData.mainData
        const formData = this.leftData.formData
        const firstData = mainData[0].segmentList
        const secondData = mainData[1] ? mainData[1].segmentList : null
        const startIndex = firstData.findIndex(i => i.startNodeId === formData.aNodeId)
        const endIndex = firstData.findIndex(i => i.endNodeId === formData.zNodeId)
        const fiberList = []
        for (let i = startIndex; i < endIndex + 1; i++) {
          firstData[i].fiberId && fiberList.push(firstData[i].fiberId)
          const index = i - startIndex
          this.mainChannel.push(firstData[i])
          this.addNode(firstData[i], index, false, 1)
          this.formateEdge(firstData[i])
          if (secondData) {
            this.mainChannel.push(secondData[i])
            this.addNode(secondData[i], index, false, 2)
            this.formateEdge(secondData[i])
          }
        }
        this.getFiberInfo(fiberList)
      },
      getFiberInfo(fiberList) {
        cableFiberApi.getByFiberIdList(fiberList).then(res => {
          this.cableData = res || {}
          this.mainRouteReady = true
          this.getAllPort()
        })
      },
      addNode(data, index, isMigrate, channelIndex) {
        const offsetY = this.channelCount === 2 ? 13 : 20
        this.formateNode(
          data.startNode,
          data.startPort,
          {
            x: 60,
            y: (isMigrate ? offsetY * this.channelCount : 0) + channelIndex * offsetY
          },
          index,
          isMigrate
        )
        this.formateNode(
          data.endNode,
          data.endPort,
          {
            x: 0,
            y: (isMigrate ? offsetY * this.channelCount : 0) + channelIndex * offsetY
          },
          index + 1,
          isMigrate
        )
      },
      formateEdge(data, isMigrate) {
        const edgeItem = {
          ...data,
          isNew: false,
          id: data.startPortId + '_' + data.endPortId,
          label: data.fiber ? data.fiber.fiberName : '',
          lineType: isMigrate ? 'migrate' : 'main',
          from: data.startPortId,
          fromCell: data.startNodeId,
          toCell: data.endNodeId,
          to: data.endPortId
        }
        this.allEdgeList.push(edgeItem)
      },
      formateNode(nodeData, portData, position, index, isMigrate) {
        const existNode = this.allNodeList.find(j => j.nodeId === nodeData.nodeId)
        const nodeItem = {
          ...nodeData,
          lineType: isMigrate ? 'migrate' : 'main',
          x: 50 + index * 200,
          y: isMigrate ? 400 : 50
        }
        const portItem = {
          ...portData,
          ...position
        }
        if (existNode) {
          existNode.portList.push(portItem)
        } else {
          this.allNodeList.push({
            ...nodeItem,
            portList: [portItem]
          })
        }
      },
      createEdge(data) {
        const item = {
          id: data.id,
          source: {
            cell: data.fromCell,
            port: data.from
          },
          target: {
            cell: data.toCell,
            port: data.to
          },
          attrs: {
            line: {
              stroke: data.lineType === 'main' ? 'green' : '#1a3eb7'
            }
          },
          router: {
            args: {
              padding: data.lineType === 'main' ? 20 : Math.random(10) * 100
            }
          },
          data: data
        }
        // console.log('createEdge', data)
        if (data.startNode.stationId !== data.endNode.stationId) {
          const cableName = data.cableName
            ? data.cableName
            : this.cableData[data.fiber.fiberId]
              ? this.cableData[data.fiber.fiberId].cableName
              : ''
          item.labels = [
            {
              markup: [
                {
                  tagName: 'rect',
                  selector: 'labelBody'
                },
                {
                  tagName: 'text',
                  selector: 'labelText'
                }
              ],
              attrs: {
                labelText: {
                  text: data.label
                },
                labelBody: {
                  ref: 'labelText',
                  refX: -8,
                  refWidth2: 16,
                  refHeight2: 1,
                  stroke: '#ddd',
                  fill: '#fff',
                  strokeWidth: 1,
                  rx: 0,
                  ry: 0
                }
              }
            },
            {
              attrs: {
                label: {
                  text: this.shownEdgeLabel.includes(cableName) ? '' : cableName,
                  x: 0,
                  y: -20
                }
              }
            }
          ]
          !!cableName && this.shownEdgeLabel.push(cableName)
        } else {
          item.label = data.label
          item.router = {
            name: 'normal'
          }
        }
        return item
      },
      createNode(data) {
        let imgName = 'AFS'
        if (data.nodeCategory === 'AFS' && data.nodeType === 'CLUSTER') {
          imgName = 'CLUSTER'
        } else {
          imgName = data.nodeCategory
        }
        return {
          shape: 'image',
          imageUrl: this.imgData[imgName],
          id: data.nodeId,
          x: data.x || 0,
          y: data.y || 0,
          attrs: {
            label: {
              text: data.nodeName
            }
          },
          data: data,
          ports: {
            items: data.items
          }
        }
      },
      createStation(data) {
        return {
          id: data.regionId,
          x: data.x || 0,
          y: data.y || 0,
          width: data.width,
          height: data.height,
          zIndex: 1,
          attrs: {
            body: {
              stroke: '#ccc',
              strokeWidth: 2,
              strokeDasharray: '5',
              fill: 'rgba(0,0,0,0)'
            },
            label: {
              text: data.regionName,
              fill: this.colorData.normal,
              fontSize: 14,
              x: 0,
              y: ~(parseInt(data.height / 2) + 15)
            }
          }
        }
      },
      createMap() {
        Shape.Edge.config({
          zIndex: 2,
          router: {
            name: 'manhattan',
            args: {
              padding: 20
            }
          },
          attrs: {
            line: {
              targetMarker: '',
              stroke: 'orange',
              strokeWidth: 2
            }
          }
        })
        Shape.Image.config({
          width: 60,
          height: 60,
          zIndex: 2,
          attrs: {
            label: {
              fill: this.colorData.normal,
              fontSize: 14,
              x: 0,
              y: -50
            }
          },
          ports: {
            groups: {
              in: {
                position: { name: 'absolute' },
                label: {
                  position: {
                    name: 'left'
                  }
                },
                attrs: {
                  text: {
                    fill: this.colorData.fontColor,
                    fontSize: 10
                  }
                }
              },
              out: {
                position: { name: 'absolute' },
                label: {
                  position: {
                    name: 'right'
                  }
                },
                attrs: {
                  text: {
                    fill: this.colorData.fontColor,
                    fontSize: 10
                  }
                }
              }
            }
          },
          portMarkup: [
            {
              tagName: 'circle',
              selector: 'portBody',
              attrs: {
                r: 5,
                magnet: true,
                stroke: '#31d0c6',
                fill: '#fff',
                strokeWidth: 2
              }
            }
          ]
        })
        const magnetAvailabilityHighlighter = {
          name: 'stroke',
          args: {
            padding: 3,
            attrs: {
              strokeWidth: 3,
              stroke: '#52c41a'
            }
          }
        }
        const that = this
        this.graph = new Graph({
          container: document.getElementById('linkTopo'),
          panning: true,
          mousewheel: {
            enabled: true,
            minScale: 0.3,
            maxScale: 2
          },
          highlighting: {
            magnetAvailable: magnetAvailabilityHighlighter
          },
          connecting: {
            snap: true,
            allowBlank: false,
            allowNode: false,
            highlight: true,
            // validateMagnet({ magnet }) {
            //   return magnet.getAttribute('port-group') !== 'in'
            // },

            validateConnection({ sourceMagnet, targetView, targetMagnet }) {
              // 只能从输出链接桩创建连接
              // if (!sourceMagnet || sourceMagnet.getAttribute('port-group') === 'in') {
              //   return false
              // }
              // console.log('targetMagnet', targetMagnet)
              // console.log('that.allNo', that.allPortList)
              const sourcePortId = sourceMagnet.getAttribute('port')
              const sourcePortData = that.topoPortData[sourcePortId]
              console.log('sourcePortData', sourcePortData)
              const targetPortId = targetMagnet.getAttribute('port')
              const targetPortData = that.topoPortData[targetPortId]
              // console.log('targetPortData', targetPortData)
              const graphData = that.graph.toJSON()
              // 查找占用端口的连线::一个端口最多两条连线
              const list = graphData.cells.filter(
                i =>
                  i.shape === 'edge' &&
                  (i.source.port === targetPortId || i.target.port === targetPortId)
              )
              // 端口有两条线就不能再链接
              if (list.length === 2) {
                return false
              }
              const connectData = list[0]
              if (connectData) {
                // 已占链接为设备内部链接，则不能内部自联
                if (
                  connectData.source.cell === connectData.target.cell &&
                  targetPortData.deviceId === sourcePortData.deviceId
                ) {
                  return false
                }
                // 已占链接为外部链接，则只能内部自联
                if (
                  connectData.source.cell !== connectData.target.cell &&
                  targetPortData.deviceId !== sourcePortData.deviceId
                ) {
                  return false
                }
              }
              // 只能同区域创建网段
              if (sourcePortData.stationId !== targetPortData.stationId) {
                return false
              }
              // 只能连接到链接桩
              if (
                !targetMagnet ||
                targetMagnet.getAttribute('port-group') === sourceMagnet.getAttribute('port-group')
              ) {
                return false
              }

              return true
            }
          },
          translating: {
            restrict(view) {
              const cell = view.cell
              if (cell.isNode()) {
                const parent = cell.getParent()
                if (parent) {
                  return parent.getBBox()
                }
              }

              return null
            }
          }
        })
        this.graph.on('edge:mouseenter', ({ cell }) => {
          if (
            !cell.data ||
            !cell.data.startNode ||
            !cell.data.endNode ||
            cell.data.startNode.stationId !== cell.data.endNode.stationId
          ) {
            return
          }
          cell.addTools([
            {
              name: 'button-remove',
              args: {
                distance: -30
              }
            }
          ])
        })

        this.graph.on('edge:mouseleave', ({ cell }) => {
          cell.removeTools()
        })
        // 网段双击
        this.graph.on('edge:dblclick', ({ e, edge }) => {
          // console.log('edge:click', e)
          // console.log('edge:click', edge)
          that.activeEdge = edge
          const segmentId = edge.data.segmentId
          that.clickPosition = {
            top: e.offsetY + 'px',
            left: e.offsetX + 'px'
          }
          // 有可选通道网段
          if (segmentId && this.ChannelData[segmentId]) {
            that.activeChannel = deepClone(edge.data)
            that.activeChannelList = this.ChannelData[segmentId]
            that.showProp = true
          }
          // 新建的网段选择AZ
          if (edge.data.isNew) {
            that.newEdgeClick(edge.data)
          }
        })
      },
      // 新建的网段选择AZ
      newEdgeClick(data) {
        console.log('newEdgeClick', data)
        const aPortList = this.nodePortData[data.startNodeId]
        const zPortList = this.nodePortData[data.endNodeId]
        this.aPortList = aPortList.filter(i => i.status !== 'MAIN')
        this.zPortList = zPortList.filter(i => i.status !== 'MAIN')
        this.activeChannel = deepClone(data)
        console.log('activeChannel', this.activeChannel)
        this.showNewProp = true
      },
      // 删除网段连线
      removeEdge({ e, x, y, edge, view }) {
        console.log('edge', edge)
        if (edge.data.isNew) {
          this.activeData = this.activeData.filter(i => i.id !== edge.id)
        } else {
          if (
            (!edge.data.endPort || !edge.data.endPort.portId) &&
            this.nodePortData[edge.data.endNodeId]
          ) {
            const endPortData = this.nodePortData[edge.data.endNodeId].find(
              i => i.portId === edge.data.endPortId
            )
            edge.data.endPort = endPortData
          }
          this.removeData.push(edge.data)
        }
        this.$emit('cutChange', this.activeData)
        console.log('this.removeData', this.removeData)
      },
      // 新增网段连线
      addEdge({ e, x, y, edge, view }) {
        edge.data = {
          isNew: true
        }
        const that = this
        setTimeout(function() {
          that.setEdgeData(edge)
        }, 1000)
      },
      // 设置新添加网段信息
      setEdgeData(edge) {
        // console.log('this.graph.toJson()', that.graph.toJSON({ diff: true }))
        console.log('addEdge', edge)
        console.log('this.removeData', this.removeData)
        const sourcePortData = this.topoPortData[edge.source.port]
        const targetPortData = this.topoPortData[edge.target.port]
        if (!edge.target.cell) return
        // 判断是否是删除后的网段重新添加
        const removeData = this.removeData.find(
          i =>
            (i.startPortId === sourcePortData.portId && i.endPortId === targetPortData.portId) ||
            (i.endPortId === sourcePortData.portId && i.startPortId === targetPortData.portId)
        )
        console.log('removeData', removeData)
        if (removeData) {
          edge.data = removeData
          edge.data.id = edge.id
          this.removeData = this.removeData.filter(i => i.id !== removeData.id)
          edge.attr('line/stroke', removeData.lineType === 'main' ? 'green' : '#1a3eb7')
          // console.log('this.removeData', this.removeData)
        } else {
          const startNode = this.allNodeList.find(i => i.nodeId === edge.source.cell)
          const endNode = this.allNodeList.find(i => i.nodeId === edge.target.cell)
          const newItem = {
            id: edge.id,
            isNew: true,
            startStationId: startNode.stationId,
            startNodeId: edge.source.cell,
            startPortId: sourcePortData.portId,
            startNode: startNode,
            startPort: sourcePortData,
            endStationId: endNode.stationId,
            endNodeId: edge.target.cell,
            endPortId: targetPortData.portId,
            endPort: targetPortData,
            endNode: endNode
          }
          edge.data = newItem
          this.activeData.push(newItem)
          this.$emit('cutChange', this.activeData)
        }
        if (edge.source.cell === edge.target.cell) {
          edge.router = {
            name: 'normal'
          }
        }
        console.log('this.activeData', this.activeData)
      },
      getSaveData() {
        const curData = this.graph.toJSON()
        return {
          curData: curData.cells.filter(i => i.shape === 'edge'),
          removeData: this.removeData,
          finalLayout: this.getMapData(),
          initTopo: this.initTopo
        }
      },
      getMapData() {
        const graphData = this.graph.toJSON()
        const mapData = deepClone(graphData)
        mapData.cells.forEach(i => {
          delete i.data
          if (i.ports) {
            i.ports.items.forEach(j => {
              delete j.data
            })
          }
        })
        return JSON.stringify(mapData)
      },
      addOutPoint() {
        this.activeNode.addPort()
      },
      // 弹窗确认改变通道
      changeChannel() {
        console.log('this.activeChannel', this.activeChannel)
        const activeEdge = deepClone(this.activeChannel)
        this.activeEdge.data = activeEdge
        console.log('this.topoPortData', this.topoPortData)
        this.topoPortData[this.activeEdge.source.port] = activeEdge.startPort
        this.topoPortData[this.activeEdge.target.port] = activeEdge.endPort
        const sourceNode = this.graph.getCellById(this.activeEdge.source.cell)
        const targetNode = this.graph.getCellById(this.activeEdge.target.cell)
        const sourcePort = this.activeEdge.source.port
        const targetPort = this.activeEdge.target.port
        // 修改端口名称显示
        sourceNode.setPortProp(
          sourcePort,
          'attrs/text/text',
          this.$utils.handleServiceI18n(this.activeChannel.startPort.bizName)
        )
        targetNode.setPortProp(
          targetPort,
          'attrs/text/text',
          this.$utils.handleServiceI18n(this.activeChannel.endPort.bizName)
        )
        const graphData = this.graph.toJSON()
        const sourceConnectData = graphData.cells.find(
          i =>
            i.shape === 'edge' &&
            ((i.source.port === sourcePort && i.target.port !== targetPort) ||
              (i.target.port === sourcePort && i.source.port !== targetPort))
        )
        const targetConnectData = graphData.cells.find(
          i =>
            i.shape === 'edge' &&
            ((i.source.port === targetPort && i.target.port !== sourcePort) ||
              (i.target.port === targetPort && i.source.port !== sourcePort))
        )
        if (sourceConnectData) {
          this.graph.removeEdge(sourceConnectData.id)
        }
        if (targetConnectData) {
          this.graph.removeEdge(targetConnectData.id)
        }
        // 修改纤芯显示
        if (this.activeEdge.data.isNew) {
          this.newEdgeChange(this.activeEdge.data)
          return
        }
        const targetEdge = this.graph.getCellById(this.activeEdge.id)
        const labels = this.activeEdge.labels
        labels[0].attrs.labelText.text = this.activeChannel.fiber
          ? this.activeChannel.fiber.fiberName
          : ''
        targetEdge.removeLabelAt(0)
        targetEdge.insertLabel(labels[0], 0)
        this.showProp = false
      },
      newEdgeChange(data) {
        this.activeData = this.activeData.map((i, index) => {
          return i.id === data.id ? data : i
        })
        console.log('this.activeData', this.activeData)
        this.$emit('cutChange', this.activeData)
        this.showNewProp = false
      },
      // 网段通道切换弹窗改变
      activeChannelChange(e) {
        const channelData = this.activeChannelList.find(i => i.channelId === e)
        this.activeChannel = channelData
      },
      aPortChange(e) {
        const portData = this.aPortList.find(i => i.portId === e)
        this.activeChannel.startPortId = e
        this.activeChannel.startPort = portData
      },
      zPortChange(e) {
        const portData = this.zPortList.find(i => i.portId === e)
        this.activeChannel.endPortId = e
        this.activeChannel.endPort = portData
      }
    }
  }
</script>
<style lang="scss">
  @import '@/assets/css/mixin.module.scss';

  .link-topo {
    .x6-node,
    .x6-node [magnet='true'] {
      cursor: pointer;
    }

    .func-btns {
      position: absolute;
      padding: 10px;
      border-radius: 5px;
      border: 1px solid #ccc;

      @include themeify {
        color: themed('textColor');
        background: themed('tableBg');
        border-color: themed('borderColor');
      }

      .channel-item {
        height: 100%;
        font-size: 14px;

        &.text-holder {
          position: absolute;
          width: 100%;
          height: 28px;
          padding: 0 30px 0 5px;
          z-index: 2;
          pointer-events: none;
        }

        span {
          width: 33%;
          line-height: 16px;
          text-align: center;
          overflow: hidden;
          text-overflow: ellipsis;
        }
      }
    }
  }
</style>
